package com.example.registerstarter.config;

import com.example.registerstarter.RegisterService;
import com.example.registerstarter.anno.RemoteReference;
import com.example.registerstarter.anno.RemoteService;
import org.aopalliance.intercept.Interceptor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**
 * @author：kangxuan
 * @date：2024/9/30 10:42 AM
 * @desc:
 */
@Component
public class RemoteServiceBeanPostProcess implements BeanPostProcessor {
    @Autowired
    private RegisterService registerService;

    private Map<Class, Object> INSTANCE_MAP = new HashMap<>();

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 获取类的属性，看看是否有RemoteReference注解
        Field[] declaredFields = bean.getClass().getDeclaredFields();
        for (Field declaredField : declaredFields) {
            if (declaredField.isAnnotationPresent(RemoteReference.class)){
                Class<?> type = declaredField.getType();
                if (!INSTANCE_MAP.containsKey(type)) {
                    // 创建代理对象
                    Object o = Proxy.newProxyInstance(
                            type.getClassLoader(),
                            new Class[]{type},
                            new InvocationHandler() {
                                @Override
                                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                    return registerService.callMethod(type.getName(), method, args);
                                }
                            }
                    );
                    INSTANCE_MAP.put(type,o);
                }
                // 注入
                declaredField.setAccessible(true);
                try {
                    declaredField.set(bean,INSTANCE_MAP.get(type));
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean.getClass().isAnnotationPresent(RemoteService.class)){
            //注册服务
            Class<?>[] interfaces = bean.getClass().getInterfaces();
            for (Class<?> anInterface : interfaces) {
                registerService.register(anInterface.getName());
            }

        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}
